<template>
	<div class="color-alpha-slider" :class="{ 'is-vertical': vertical }">
		<div ref="bar" class="color-alpha-slider__bar" :style="{
			background
		}" @click="handleClick"></div>
		<div ref="thumb" class="color-alpha__thumb" :style="{ left: thumbLeft + 'px', top: thumbTop + 'px' }"></div>
	</div>
</template>

<script setup lang="ts">
import draggable from '../util/draggable'
import type { Nullable } from '../color-picker'
import { AlphaSliderProps } from "../color-picker";

const props = defineProps(AlphaSliderProps);

const instance = getCurrentInstance() //当前实例
const bar = shallowRef<Nullable<HTMLElement>>(null) //管理bar
const thumb = shallowRef<Nullable<HTMLElement>>(null) //管理thumb
const thumbLeft = ref<number>(0) //管理thumb左
const thumbTop = ref<number>(0) //管理thumb右
const background = ref<any>(null) //管理background

/**
 * 监听color值
 */
watch(
	() => props.color?.get('alpha'),
	() => {
		update()
	}
)

/**
 * 监听color值
 */
watch(
	() => props.color?.value,
	() => {
		update()
	}
)

/**
 * handleClick点击事件
 * @param event
 */
const handleClick = (event: Event) => {
	const target = event.target
	if (target !== thumb.value) {
		handleDrag(event)
	}
}

/**
 * handleDrag拖拽事件
 * @param event
 */
const handleDrag = (event: any) => {
	const ele = instance?.vnode.el as HTMLElement
	const rect = ele.getBoundingClientRect()
	if (!props.vertical) {
		let left = event.clientX - rect.left
		left = Math.max((thumb.value as HTMLElement).offsetWidth / 2, left)
		left = Math.min(left, rect.width - (thumb.value as HTMLElement).offsetWidth / 2)
		props.color?.set(
			'alpha',
			Math.round(
				((left - (thumb.value as HTMLElement).offsetWidth / 2) /
					(rect.width - (thumb.value as HTMLElement).offsetWidth)) *
				100
			)
		)
	} else {
		let top = event.clientY - rect.top
		top = Math.max((thumb.value as HTMLElement).offsetHeight / 2, top)
		top = Math.min(top, rect.height - (thumb.value as HTMLElement).offsetHeight / 2)

		props.color?.set(
			'alpha',
			Math.round(
				((top - (thumb.value as HTMLElement).offsetHeight / 2) /
					(rect.height - (thumb.value as HTMLElement).offsetHeight)) *
				100
			)
		)
	}
}

/**
 * update更新事件
 */
const update = () => {
	thumbLeft.value = getThumbLeft()
	thumbTop.value = getThumbTop()
	background.value = getBackground()
}

/**
 * 获取Thumb左侧
 */
const getThumbLeft = (): number => {
	if (props.vertical) return 0
	const ele = instance?.vnode.el
	const alpha = props.color?.get('alpha')

	if (!ele) return 0
	return Math.round(
		(alpha * (ele.offsetWidth - (thumb.value as HTMLElement).offsetWidth / 2)) / 100
	)
}

/**
 * 获取Thumb顶部
 */
const getThumbTop = (): number => {
	const ele = instance?.vnode.el
	if (!props.vertical) return 0
	const alpha = props.color?.get('alpha')
	if (!ele) return 0
	return Math.round(
		(alpha * (ele.offsetHeight - (thumb.value as HTMLElement).offsetHeight / 2)) / 100
	)
}

/**
 * 获取背景色
 */
const getBackground = () => {
	if (props.color && props.color.value) {
		const { r, g, b } = props.color.toRgb()
		return `linear-gradient(to right, rgba(${r}, ${g}, ${b}, 0) 0%, rgba(${r}, ${g}, ${b}, 1) 100%)`
	}
	return null
}

defineExpose({ update });
onMounted(() => {
	const dragConfig = {
		drag: (event: any) => {
			handleDrag(event)
		},
		end: (event: any) => {
			handleDrag(event)
		}
	}
	draggable(bar.value as HTMLElement, dragConfig)
	draggable(thumb.value as HTMLElement, dragConfig)
	update()
})
</script>
